package view;

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import model.Filter;
import model.MeetingInfo;
import model.MeetingMail;
import model.Template;

import resources.ResourceProvider;

/**
 * This is a class to represent JPanel to display option button button area.
 * Client will have button to create new message, to send a message, to delete a message,move button to move 
 * an email from one folder to another, to cancel a message, to save a message to draft and a reply button 
 * to reply to the email to the sender 
 *
 */
public class OptionButtonArea extends JPanel implements Observable
{
  private static final long serialVersionUID = -1043251887661504219L;
  
  private EmailApplicationView emailApplicationView;	
  private JButton newMessageButton;
  private JButton deleteButton;
  private JButton moveToButton;
  private JButton sendToButton;
  private JButton cancelButton;
  private JButton saveToDraftButton;
  private JButton replyButton;
  private JButton createTemButton;
  private JButton saveTemButton;
  private JButton newMeetingButton;
  private JButton searchButton;
  private JButton templateButton;
  private JButton filterButton;
  private JButton createFilterButton;
  private JButton filterSettingButton;
  private LinkedList<Observer> observers;  
  private JButton acceptButton;
  private JButton rejectButton;
  private JButton editButton;
  private JButton myMeetingButton;
  private JTextField textField;
  private JButton meetingUpdateButton;
  private JButton deleteMeeting;

 /**
  * Constructor OptionButtonArea
  * @param emailApplicationView the email application view reference
  */
  public OptionButtonArea(EmailApplicationView emailApplicationView) 
  {
	  TitledBorder title = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black), "Actions");
	  this.setBorder(title);
	  this.setLayout(new FlowLayout());	  
	  this.emailApplicationView = emailApplicationView;
  }
  
 /**
  * Initially the client will only have new message button, new meeting button, search button and template button
  */
  public void initialize()
  {
	  this.observers = new LinkedList<Observer>();
	  this.addNewMessageButton();
	  this.addNewMeetingButton();
      this.addMyMeetingButton();
	  this.addSearchButton();
	  this.addTemplateButton();
      this.addFilterButton();
  }
  
  /**
   * add template button
   */
  public void addTemplateButton()
  {
	  templateButton = new JButton(ResourceProvider.TEMPLATES);
	  templateButton.addActionListener(new ActionListener() {
          
          public void actionPerformed(ActionEvent e)
          {
              notifyObservers(ResourceProvider.TEMPLATES);
              
              OptionButtonArea.this.displayButtonsForTemplates();
          }
      });
      this.add(templateButton); 
  }
  
  /**
   * add filter button
   */
   public void addFilterButton()
   {
       filterButton = new JButton(ResourceProvider.FILTERS);
       filterButton.addActionListener(new ActionListener() {
           
           public void actionPerformed(ActionEvent e)
           {
               notifyObservers(ResourceProvider.FILTERS);
               
               OptionButtonArea.this.displayButtonsForFilters();
           }
       });
       this.add(filterButton); 
   }
   
    /**
     * display relevant buttons for Filters
     */
    public void displayButtonsForFilters()
    {
        this.removeAll();     
        this.addCreateFilterButton();
        this.addEditOrDeleteFilterOptions();
        this.addFilterSettingButton();
        this.addCancelButton();
        this.revalidate();
        this.repaint();     
    }

    /**
     * add Edit/Delete Filter options
     */
    public void addEditOrDeleteFilterOptions()
    {
        final String defaultMessage = "<Select Filter to Edit/Delete>";

        String user = OptionButtonArea.this.emailApplicationView.getController().getUser();
        String path = ResourceProvider.getRootFolderPath(ResourceProvider.FILTERS, user);
        
        final List<Filter> filterList = OptionButtonArea.this.emailApplicationView.getController().requestFiltersFromPersistence(path);
        
        List<String> filtNameList = new LinkedList<String>();
        filtNameList.add(defaultMessage);

        for(Filter fiL: filterList)
        {
            filtNameList.add(fiL.getFilterName());
        }
        
        String[] names = filtNameList.toArray(new String[]{});
        
        // add combo box
        final JComboBox<String> combox = new JComboBox<String>(names);
         combox.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent e) 
            {   
                String selection = (String)combox.getSelectedItem();
                
                if(!defaultMessage.equals(selection))
                {
                    for(Filter filtR : filterList)
                    {
                        if(filtR.getFilterName().equals(selection))
                        {
                            OptionButtonArea.this.emailApplicationView.getMailDisplayArea().displayFilter(filtR);
                            break;
                        }
                    }
                    
                    OptionButtonArea.this.displayButtonsToEditOrDelete();
                }
            }
         });
         this.add(combox);
    }

  
 /**
  * add New Message button
  */
  public void addNewMessageButton()
  {
      newMessageButton = new JButton(ResourceProvider.NEW_MESSAGE);
      newMessageButton.addActionListener(new ActionListener() {
          
          public void actionPerformed(ActionEvent e)
          {
              notifyObservers(ResourceProvider.NEW_MESSAGE);
              OptionButtonArea.this.displayButtonsForNewMessage();              
          }
      });
      this.add(newMessageButton);
  }
  
  /**
   * add New Meeting button
   */
  public void addNewMeetingButton()
  {
      newMeetingButton = new JButton(ResourceProvider.NEW_MEETING);
      newMeetingButton.addActionListener(new ActionListener() {
          
          public void actionPerformed(ActionEvent e)
          {
              notifyObservers(ResourceProvider.NEW_MEETING);
              OptionButtonArea.this.displayButtonsForNewMeeting();
          }
      });
      this.add(newMeetingButton);
  }
  
   /**
    * display Search options panel
    */
  public void displaySearchOptions()
  {
     this.removeAll();     
     this.addCancelButton();     
     this.revalidate();
     this.repaint();       
  }

    /**
     * add Search button
     */
  public void addSearchButton()
  {
      searchButton = new JButton(ResourceProvider.SEARCH);
      searchButton.addActionListener(new ActionListener() 
      {
          public void actionPerformed(ActionEvent e)
          {
              notifyObservers(ResourceProvider.SEARCH);
              OptionButtonArea.this.displaySearchOptions();
          }
      });
      this.add(searchButton);
  }

  /**
   * add Send button
   */
  public void addSendButton()
  {
      sendToButton = new JButton(ResourceProvider.SEND_OPTION);
      sendToButton.addActionListener(new ActionListener() {
          
          public void actionPerformed(ActionEvent e)
          {
              notifyObservers(ResourceProvider.SEND_OPTION);
          }
      });
      this.add(sendToButton);
  }
  
  /**
   * add Cancel button
   */
  public void addCancelButton()
  {
      cancelButton = new JButton(ResourceProvider.CANCEL_OPTION);
      cancelButton.addActionListener(new ActionListener() {
          
          public void actionPerformed(ActionEvent e)
          {
              notifyObservers(ResourceProvider.CANCEL_OPTION);               
          }
      });
      this.add(cancelButton);
  }
  
  /**
   * add Save to draft button
   */
  public void addSaveToDraftButton()
  {
      saveToDraftButton = new JButton(ResourceProvider.SAVE_TO_DRAFT_OPTION);
      saveToDraftButton.addActionListener(new ActionListener() {
          
          public void actionPerformed(ActionEvent e)
          {
             notifyObservers(ResourceProvider.SAVE_TO_DRAFT_OPTION);
          }
      });
      this.add(saveToDraftButton);
  }
  
  /**
   * add Delete button 
   */
  public void addDeleteButton()
  {
       deleteButton = new JButton(ResourceProvider.DELETE_OPTION);
       deleteButton.addActionListener(new ActionListener() 
       {       
           public void actionPerformed(ActionEvent e)
           {
               int delete = JOptionPane.showConfirmDialog(OptionButtonArea.this.getParent().getParent().getParent().getParent(), "Are you sure to delete?", "Warning",
                      JOptionPane.YES_NO_OPTION);
               if(delete == JOptionPane.OK_OPTION)
                 {
                   notifyObservers(ResourceProvider.DELETE_OPTION); 
                 }
    
           }
       });

      this.add(deleteButton);   
  }
  
  /**
   * add move to button
   */
  public void addMoveToButton()
  {
      moveToButton = new JButton(ResourceProvider.MOVE_TO);
      moveToButton.addActionListener(new ActionListener() {
          
          public void actionPerformed(ActionEvent e)
          {
              notifyObservers(ResourceProvider.MOVE_TO);
          }
      });
      this.add(moveToButton); 
  }
  
  /**
   * add reply button
   */
  public void addReplyButton()
  {
      replyButton = new JButton(ResourceProvider.REPLY_OPTION);
      replyButton.addActionListener(new ActionListener() {
          
          public void actionPerformed(ActionEvent e)
          {
              notifyObservers(ResourceProvider.REPLY_OPTION);
          }
      });
      this.add(replyButton);        
  }

  /**
   * register observer component
   * @param observer the observer to register
   */
	public void registerObserver(Observer observer) 
	{
	    observers.add(observer);	
	}
	
	/**
	 * unregister observer component
     * @param observer the observer to unregister
	 */
	public void unRegisterObserver(Observer observer) 
	{
	    observers.remove(observer);	
	}
	
	/**
	 * notify observers with the give action on UI
	 * @action action the action that taken place
	 */
	public void notifyObservers(String action) 
	{
		for (Observer ob : observers) 
		{
	        ob.update(action);
	    }
	}
	
	/**
	 * get email application view reference 
	 * @return the reference of the email application view
	 */
	public EmailApplicationView getEmailApplicationView()
    {
        return emailApplicationView;
    }
	
	/**
	 * check if file exist in the give path, if yes return true, otherwise return false
	 * @param path the given path
	 * @return return true if the file exist otherwise false
	 */
	private boolean doesFileExist(String path)
	{
	       File file = new File(path);
	       String[] files = file.list();
	       int numOffiles = files.length;
	       if( numOffiles == 0)
	       {
	           return false;
	       }
	       else
	       {
	           String seperator = ResourceProvider.getFilePathSeperator();
	           String user = this.emailApplicationView.getController().getUser();
	           String userFolderPath = ResourceProvider.PERSISTENCE_USERS_FOLDER_PATH + user;
	           String mailboxFolderPath = userFolderPath + seperator + ResourceProvider.MAILBOX;
	           String inboxFolderPath = mailboxFolderPath + seperator + ResourceProvider.INBOX + seperator;
	           if(path.contains(inboxFolderPath))
	           {
	               return doesEmailExist(path);
	           }
	           else
	           {
	               boolean exist = false;
                   File[] inboxFiles = file.listFiles();
                   for(File inboxfile : inboxFiles)
                   {
                       if(!inboxfile.isDirectory() && !(inboxfile.getName().startsWith(".")))
                       {
                           exist = true;
                           break;
                       }
                       else
                       {
                           exist = false;
                       }
                   }
                   return exist;
	           }
	       }
	}
	
	/**
	 * check if email exist in the given path, return true if yes, otherwise return false
	 * @param path the given path
	 * @return returns true if the email exist in the given path else false
	 */
	public boolean doesEmailExist(String path)
	{
	    File file = new File(path);
        File[] files = file.listFiles();
        for(File fl : files)
        {
            if(!(fl.getName().startsWith(".")))
            {
                if(fl.isDirectory())
                {
                    this.doesEmailExist(fl.getPath());
                }
                else
                {
                    return true;
                }
            } 
        }
        return false;
	}

	/**
	 * display buttons in the panel
	 * @param persistenceFilePath the persistence path
	 */
    public void displayButtons(String persistenceFilePath)
    {
        this.removeAll();
        
        // add buttons
        this.addNewMessageButton();
        this.addNewMeetingButton();
        if(this.doesFileExist(persistenceFilePath))
        {
            this.addDeleteButton();
            
            if(persistenceFilePath.contains(ResourceProvider.INBOX) || persistenceFilePath.contains(ResourceProvider.TRASH))
            {
                this.addMoveToButton();
            }   
        } 
        this.addMyMeetingButton();
        this.addSearchButton();
        this.addTemplateButton();
     
        this.revalidate();
        this.repaint(); 
    }
    
    /**
     * display button for new message
     */
    public void displayButtonsForNewMessage()
    {
        this.removeAll();      
        this.addLoadTemplateOptions();
        this.addSendButton();
        this.addSaveToDraftButton();     
        this.addCancelButton();        
        
        this.revalidate();
        this.repaint();
    }
    
    /**
     * display button for new meeting
     */
    public void displayButtonsForNewMeeting()
    {
        this.removeAll();
        this.addLoadTemplateOptions();
        this.addSendButton();
        this.addSaveToDraftButton();        
        this.addCancelButton();

        this.revalidate();
        this.repaint();
    }

    /**
     * display button for the email
     * @param reply if the user want to reply to specific email send and save to draft button will activate
     */
    public void displayButtonsForEmail(boolean reply)
    {
        this.removeAll();
        
        if(reply)
        {
            this.addSendButton();
            this.addSaveToDraftButton(); 
        }
        else
        {
           this.addReplyButton();  
           
        }
        
        this.addCancelButton();
        
        this.revalidate();
        this.repaint();        
    }
    
    /**
     * display template button area
     */
    public void displayButtonsForTemplates() 
    {
        this.removeAll();          
        this.addCreateTemButton();
        this.addEditOrDeleteTemplateOptions(); 
        this.addCancelButton();
        this.revalidate();
        this.repaint();
    	
    }
    
    /**
     * display create button area
     */
    public void displayButtonsForCreateTemplate() 
    {
        this.removeAll();           
        this.addSaveButton();
        this.addCancelButton();     
        this.revalidate();
        this.repaint();      
    }

    /**
     * add an combo box for template set, select one template for loading 
     */
    public void addLoadTemplateOptions()
    {
        final String defaultMessage = "<Select Template to Apply>";

        String user = OptionButtonArea.this.emailApplicationView.getController().getUser();
        String path = ResourceProvider.getRootFolderPath(ResourceProvider.TEMPLATES, user);
        
        final List<Template> templateList = OptionButtonArea.this.emailApplicationView.getController().requestTemplatesFromPersistence(path);
        
        List<String> tempLNameList = new LinkedList<String>();
        tempLNameList.add(defaultMessage);

        for(Template tempL: templateList)
        {
            tempLNameList.add(tempL.getTemplateName());
        }
        
        String[] names = tempLNameList.toArray(new String[]{});
        
        // add combo box
        final JComboBox<String> combox = new JComboBox<String>(names);
         combox.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent e) 
            {
                String selection = (String)combox.getSelectedItem();
                
                if(!defaultMessage.equals(selection))
                {
                    for(Template tempL : templateList)
                    {             
                        if(tempL.getTemplateName().equals(selection))
                        {
                            OptionButtonArea.this.emailApplicationView.getMailDisplayArea().loadTemplate(tempL);
                            break;
                        }
                    }
               }
             }
         });
         this.add(combox);
    
    }
    
    /**
     * add an combo box for template set, select one template for editing or deleting  
     */
    public void addEditOrDeleteTemplateOptions()
    {
        final String defaultMessage = "<Select Template to Edit/Delete>";

        String user = OptionButtonArea.this.emailApplicationView.getController().getUser();
        String path = ResourceProvider.getRootFolderPath(ResourceProvider.TEMPLATES, user);
        
        final List<Template> templateList = OptionButtonArea.this.emailApplicationView.getController().requestTemplatesFromPersistence(path);
        
        List<String> tempLNameList = new LinkedList<String>();
        tempLNameList.add(defaultMessage);

        for(Template tempL: templateList)
        {
            tempLNameList.add(tempL.getTemplateName());
        }
        
        String[] names = tempLNameList.toArray(new String[]{});
        
        // add combo box
        final JComboBox<String> combox = new JComboBox<String>(names);
         combox.addActionListener(new ActionListener()
         {
            public void actionPerformed(ActionEvent e) 
            {
                String selection = (String)combox.getSelectedItem();
                
                if(!defaultMessage.equals(selection))
                {  
                    for(Template tempL : templateList)
                    {
                        if(tempL.getTemplateName().equals(selection))
                        {
                            OptionButtonArea.this.emailApplicationView.getMailDisplayArea().loadTemplate(tempL);
                            break;
                        }
                    }
                    notifyObservers(ResourceProvider.LOAD_OPTION);
                }           
            }
         });
         this.add(combox);
    }

    /**
     * display button area of editing or deleting template
     */
    public void displayButtonsToEditOrDelete()
    {
        this.removeAll();     
        this.addSaveButton();
        this.addDeleteButton();
        this.addCancelButton();       
        this.revalidate();
        this.repaint();
    }

    /**
     * add create template button
     */
	public void addCreateTemButton() 
	{
		createTemButton = new JButton(ResourceProvider.CREATETEM_OPTION);
		createTemButton.addActionListener(new ActionListener() 
		{          
	          public void actionPerformed(ActionEvent e)
	          {
	              notifyObservers(ResourceProvider.CREATETEM_OPTION);
	              OptionButtonArea.this.displayButtonsForCreateTemplate();
	          }
	      });
	      this.add(createTemButton);
	}

    /**
     * add create filter button
     * 
     */
    public void addCreateFilterButton() 
    {
        createFilterButton = new JButton(ResourceProvider.CREATE_FILTER_OPTION);
        createFilterButton.addActionListener(new ActionListener() {
              
              public void actionPerformed(ActionEvent e)
              {
                  notifyObservers(ResourceProvider.CREATE_FILTER_OPTION);              
                  OptionButtonArea.this.displayButtonsForCreateTemplate();
              }
          });
          this.add(createFilterButton);
    }
    
    /**
     * add filter setting button
     *  
     */
    public void addFilterSettingButton() 
    {
        filterSettingButton = new JButton(ResourceProvider.FILTER_SETTING);
        filterSettingButton.addActionListener(new ActionListener() {
              
              public void actionPerformed(ActionEvent e)
              {
                  notifyObservers(ResourceProvider.FILTER_SETTING);
              }
          });
          this.add(filterSettingButton);
    } 
    
	/**
	 * add save button
	 */
	public void addSaveButton()
	{
		saveTemButton = new JButton(ResourceProvider.SAVE_OPTION);
		saveTemButton.addActionListener(new ActionListener() {
	          
	          public void actionPerformed(ActionEvent e)
	          {
	              notifyObservers(ResourceProvider.SAVE_OPTION);
	          }
	      });
	      this.add(saveTemButton);
	}

	/**
	 * display buttons for meeting email: Accept or Reject
	 * @param email the email
	 */
    public void displayButtonsForMeetingEmail(MeetingMail email)
    {
        this.removeAll();
        
        String meetingID = email.getMeetingId();
        String user = OptionButtonArea.this.emailApplicationView.getController().getUser();
        String meetingPath = ResourceProvider.getRootFolderPath(ResourceProvider.MEETING, user);
        String meetingDataPath = meetingPath + ResourceProvider.getFilePathSeperator() + meetingID + ".json";
        
        String status = "";
        
        //check if meetingID is already have meeting info
        if(new File(meetingDataPath).exists())
        {
            MeetingInfo meetingInfo = OptionButtonArea.this.emailApplicationView.getController().requestMeetingInfo(meetingDataPath);
            Map<Integer, String> data  = meetingInfo.meetingParticipantData;
            status = data.get(user.hashCode());
        } 
        
        if(status.equals(MeetingInfo.MEETING_NO_ACTION))
        {
            this.addAcceptButton();
            this.addRejectButton();
        }
        else if(status.equals(MeetingInfo.MEETING_REJECTED))    
        {
            this.displayMessage("You did Reject the meeting!");
            return;
        }
        else if(status.equals(MeetingInfo.MEETING_CANCELLED))
        {
            this.displayMessage("Meeting is Cancelled!");
            return; 
        }
       
            this.addEditButton();

                
        this.revalidate();
        this.repaint();           
    }
    
	/**
	 * add meeting message TextField
	 * @param message the given message
	 */
    public void addTextField(String message)
    {
        this.textField = new JTextField(message);
        this.textField.setSize(500, 30);
        this.textField.setEditable(false);
        this.add(this.textField);
    }

	/**
	 * add edit button
	 */
    public void addEditButton()
    {
        editButton = new JButton(ResourceProvider.EDIT);
        editButton.addActionListener(new ActionListener() {
            
            public void actionPerformed(ActionEvent e)
            {
                notifyObservers(ResourceProvider.EDIT);
                OptionButtonArea.this.displayMeetingEditOptionButtons();
            }
        });
        this.add(editButton);         
    }

	/**
	 * display button area if clicking meeting edit button
	 */
    public void displayMeetingEditOptionButtons()
    {
        this.removeAll();
        this.addMeetingUpdateButton();
        this.addDeleteMeetingButton();
        this.addCancelButton();
        this.revalidate();
        this.repaint();          
    }
    
	/**
	 * display button area after clicking my meeting
	 * @param meetingButton the boolean to display meeting button or not
	 */
    public void displayNothing(boolean meetingButton)
    {
        this.removeAll();
        if(meetingButton)
        {
            this.addMyMeetingButton();
        }
        this.revalidate();
        this.repaint();
    }

	/**
	 * add meeting update button
	 */
    public void addMeetingUpdateButton()
    {
        meetingUpdateButton = new JButton(ResourceProvider.UPDATE_MEETING);
        meetingUpdateButton.addActionListener(new ActionListener() {
            
            public void actionPerformed(ActionEvent e)
            {
                notifyObservers(ResourceProvider.UPDATE_MEETING);               
            }
        });
        this.add(meetingUpdateButton);      
    }
    
	/**
	 * add delete meeting button
	 */
    public void addDeleteMeetingButton()
    {
        deleteMeeting = new JButton(ResourceProvider.DELETE_MEETING);
        deleteMeeting.addActionListener(new ActionListener() {
            
            public void actionPerformed(ActionEvent e)
            {
                notifyObservers(ResourceProvider.DELETE_MEETING);               
            }
        });
        this.add(deleteMeeting);      
    }
    
    /**
     * add edit button
     */
    public void addMyMeetingButton()
    {
        myMeetingButton = new JButton(ResourceProvider.MY_MEETING);
        myMeetingButton.addActionListener(new ActionListener() {
            
            public void actionPerformed(ActionEvent e)
            {
                notifyObservers(ResourceProvider.MY_MEETING);
                OptionButtonArea.this.displayNothing(false);
            }
        });
        this.add(myMeetingButton);         
    }

	/**
	 * add reject button
	 */
    public void addRejectButton()
    {
        rejectButton = new JButton(ResourceProvider.REJECT);
        rejectButton.addActionListener(new ActionListener() {
            
            public void actionPerformed(ActionEvent e)
            {
                notifyObservers(ResourceProvider.REJECT);
            }
        });
        this.add(rejectButton);        
    }

	/**
	 * add accept button
	 */
    public void addAcceptButton()
    {
        acceptButton = new JButton(ResourceProvider.ACCEPT);
        acceptButton.addActionListener(new ActionListener() {
            
            public void actionPerformed(ActionEvent e)
            {
                notifyObservers(ResourceProvider.ACCEPT);
            }
        });
        this.add(acceptButton); 
    }

	/**
	 * display the message String that was input in the TextField
	 * @param message the given message to display
	 */
    public void displayMessage(String message)
    {
        this.removeAll();    
        this.addTextField(message);                 
        this.revalidate();
        this.repaint(); 
    }

	/**
	 * display the meeting message with 'Accept' and 'Reject' options 
     * @param message the given message to display
	 */
    public void displayMessageAcceptRejectMeetingUpdate(String message)
    {
        this.removeAll();
        this.addAcceptButton();
        this.addTextField(message);      
        this.addRejectButton();           
        this.revalidate();
        this.repaint();         
    }
 
}
